From: Giovanni Campagna Date: Tue, 7 Aug 2012 14:49:22 +0000 (+0200) Subject: Login/UnlockDialog: don't reset immediately if auth fails X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~1013^2^2~5961 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=db20a54861f141cbbb51e5af786e77c5c3220ef7;p=gnome-shell.git Login/UnlockDialog: don't reset immediately if auth fails Instead of showing a notification, add a small message immediately below the entry, and give the user two more attempts to login, before going back to the welcome or lock screen. https://bugzilla.gnome.org/show_bug.cgi?id=682544 --- diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index 98a69dd10..ec4eabece 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -2189,6 +2189,10 @@ StButton.popup-menu-item:insensitive { background-gradient-end: #74a0d0; } +.login-dialog-message-warning { + color: orange; +} + .unlock-dialog-user-name-container { spacing: .4em; } diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js index 7bedf451a..c6ac0301d 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -647,7 +647,7 @@ const LoginDialog = new Lang.Class({ this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient); this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion)); - this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed)); + this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage)); this._userVerifier.connect('reset', Lang.bind(this, this._onReset)); this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint)); @@ -715,6 +715,10 @@ const LoginDialog = new Lang.Class({ x_fill: true, y_fill: false, x_align: St.Align.START }); + + this._promptMessage = new St.Label({ visible: false }); + this._promptBox.add(this._promptMessage, { x_fill: true }); + this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint-message' }); this._promptLoginHint.hide(); this._promptBox.add(this._promptLoginHint); @@ -797,6 +801,8 @@ const LoginDialog = new Lang.Class({ }, _onReset: function(client, serviceName) { + this._promptMessage.hide(); + let tasks = [this._hidePrompt, new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel, @@ -826,6 +832,12 @@ const LoginDialog = new Lang.Class({ this._sessionList.setActiveSession(sessionId); }, + _showMessage: function(userVerifier, message, styleClass) { + this._promptMessage.text = message; + this._promptMessage.styleClass = styleClass; + GdmUtil.fadeInActor(this._promptMessage); + }, + _showLoginHint: function(verifier, message) { this._promptLoginHint.set_text(message) GdmUtil.fadeInActor(this._promptLoginHint); @@ -1081,10 +1093,6 @@ const LoginDialog = new Lang.Class({ })); }, - _onVerificationFailed: function() { - this._userVerifier.cancel(); - }, - _onNotListedClicked: function(user) { let tasks = [function() { return this._userList.hideItems(); diff --git a/js/gdm/util.js b/js/gdm/util.js index d2e537a4c..681c0a69b 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -2,6 +2,7 @@ const Gio = imports.gi.Gio; const Lang = imports.lang; +const Mainloop = imports.mainloop; const Signals = imports.signals; const Batch = imports.gdm.batch; @@ -19,6 +20,7 @@ const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen'; const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication'; const BANNER_MESSAGE_KEY = 'banner-message-enable'; const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text'; +const ALLOWED_FAILURES_KEY = 'allowed-failures'; const LOGO_KEY = 'logo'; @@ -81,6 +83,8 @@ const ShellUserVerifier = new Lang.Class({ this._fprintManager = new Fprint.FprintManager(); this._realmManager = new Realmd.Manager(); + + this._failCounter = 0; }, begin: function(userName, hold) { @@ -242,7 +246,7 @@ const ShellUserVerifier = new Lang.Class({ // to indicate the user can swipe their finger instead this.emit('show-login-hint', _("(or swipe finger)")); } else if (serviceName == PASSWORD_SERVICE_NAME) { - Main.notifyError(info); + this.emit('show-message', info, 'login-dialog-message-info'); } }, @@ -251,7 +255,7 @@ const ShellUserVerifier = new Lang.Class({ // users who haven't enrolled their fingerprint. if (serviceName != PASSWORD_SERVICE_NAME) return; - Main.notifyError(problem); + this.emit('show-message', problem, 'login-dialog-message-warning'); }, _showRealmLoginHint: function() { @@ -290,8 +294,10 @@ const ShellUserVerifier = new Lang.Class({ }, _onReset: function() { - this._userVerifier.run_dispose(); - this._userVerifier = null; + this.clear(); + + // Clear previous attempts to authenticate + this._failCounter = 0; this.emit('reset'); }, @@ -300,12 +306,34 @@ const ShellUserVerifier = new Lang.Class({ this.emit('verification-complete'); }, + _verificationFailed: function() { + // For Not Listed / enterprise logins, immediately reset + // the dialog + // Otherwise, we allow ALLOWED_FAILURES attempts. After that, we + // go back to the welcome screen. + + if (!this._userName || + (++this._failCounter) == this._settings.get_int(ALLOWED_FAILURES_KEY)) { + // Allow some time to see the message, then reset everything + Mainloop.timeout_add(3000, Lang.bind(this, function() { + this.cancel(); + + this._onReset(); + })); + } else { + this.clear(); + this.begin(this._userName, new Batch.Hold()); + } + + this.emit('verification-failed'); + }, + _onConversationStopped: function(client, serviceName) { // if the password service fails, then cancel everything. // But if, e.g., fingerprint fails, still give // password authentication a chance to succeed if (serviceName == PASSWORD_SERVICE_NAME) { - this.emit('verification-failed'); + this._verificationFailed(); } this.emit('hide-login-hint'); diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js index da10cecc1..b18c18da0 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -89,13 +89,15 @@ const UnlockDialog = new Lang.Class({ this._userName = GLib.get_user_name(); this._user = this._userManager.get_user(this._userName); + this._failCounter = 0; + this._greeterClient = new Gdm.Client(); this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient, { reauthenticationOnly: true }); - this._userVerifier.connect('reset', Lang.bind(this, this._reset)); this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion)); + this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage)); this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete)); - this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed)); + this._userVerifier.connect('reset', Lang.bind(this, this._onReset)); this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint)); this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint)); @@ -122,6 +124,9 @@ const UnlockDialog = new Lang.Class({ this.contentLayout.add_actor(this._promptLayout); + this._promptMessage = new St.Label({ visible: false }); + this.contentLayout.add(this._promptMessage, { x_fill: true }); + this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint' }); this._promptLoginHint.hide(); this.contentLayout.add_actor(this._promptLoginHint); @@ -135,7 +140,6 @@ const UnlockDialog = new Lang.Class({ this.setButtons([cancelButton, this._okButton]); this._updateOkButton(false); - this._reset(); let otherUserLabel = new St.Label({ text: _("Log in as another user"), style_class: 'login-dialog-not-listed-label' }); @@ -150,6 +154,9 @@ const UnlockDialog = new Lang.Class({ { x_align: St.Align.START, x_fill: false }); + let batch = new Batch.Hold(); + this._userVerifier.begin(this._userName, batch); + GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() { this.emit('loaded'); return false; @@ -165,9 +172,10 @@ const UnlockDialog = new Lang.Class({ this._okButton.button.reactive = sensitive; }, - _reset: function() { - this._userVerifier.clear(); - this._userVerifier.begin(this._userName, new Batch.Hold()); + _showMessage: function(userVerifier, message, styleClass) { + this._promptMessage.text = message; + this._promptMessage.styleClass = styleClass; + GdmUtil.fadeInActor(this._promptMessage); }, _onAskQuestion: function(verifier, serviceName, question, passwordChar) { @@ -207,13 +215,13 @@ const UnlockDialog = new Lang.Class({ this.emit('unlocked'); }, - _onVerificationFailed: function() { - this._userVerifier.cancel(); + _onReset: function() { this.emit('failed'); }, _escape: function() { - this._onVerificationFailed(); + this._userVerifier.cancel(); + this.emit('failed'); }, _otherUserClicked: function(button, event) {